<?php
/**
 * Created by PhpStorm.
 * User: Drunk
 * Date: 2016-11-27
 * Time: 2:11
 */

namespace drunk;

class file{
    public static function write($filename, $content, $mode='wb'){
        if (!file_exists(dirname($filename))) mkdir(dirname($filename), 0777, true);
        if (false === ($file = fopen($filename, $mode))) return false;
        fwrite($file, $content);
        return fclose($file);
    }

    public static function lists_file($paths_root, $match = null, $filter = null, $depth = 0){
        return self::lists($paths_root, $match, $filter, $depth, 'file');
    }

    public static function lists_dir($paths_root, $match = null, $filter = null, $depth = 0){
        return self::lists($paths_root, $match, $filter, $depth, 'dir');
    }

    /**
     * 取目录文件列表
     * @param string|array $paths_root
     * @param string|array $match
     * @param string|array $filter
     * @param int $depth
     * @param string $type
     * @return array
     */
    public static function lists($paths_root, $match = null, $filter = null, $depth = 0, $type = 'all'){
        if (empty($match)) $match = [];
        if (empty($filter)) $filter = [];
        if (!array_key_exists($type, ['file'=>1, 'dir'=>1])) $type = 'all';
        $lists = [];
        foreach ((array) $paths_root as $path_root){
            $list = self::_lists($path_root, (array) $match, (array) $filter, (int) $depth, $type);
            if (!empty($list)) $lists = array_merge($lists, $list);
        }
        return $lists;
    }

    private static function _lists($path_root, $match, $filter, $depth, $type, $level = 1){
        $is_deepest = $depth === $level;
        $lists_dir = scandir($path_root);
        if (false === $lists_dir) return false;
        $lists_dir = array_filter($lists_dir, function($file_name){ // 过滤掉当前与上级目录名
            return !array_key_exists($file_name, ['.'=>1, '..'=>1]);
        });
        if (empty($lists_dir)) return null;
        $lists = [];
        $path_root = realpath($path_root);
        foreach ($lists_dir as $k=>$v) {
            $file_path = $path_root . DIRECTORY_SEPARATOR . $v;
            if (self::_fnmatch_array($filter, $file_path)) continue; // 过滤
            if (is_dir($file_path)){
                $is_matched = empty($match) || self::_fnmatch_array($match, $file_path);
                if ($is_deepest) { // 若为最深匹配
                    if (!$is_matched) continue; // 若未匹配到, 则跳过
                    if ($type === 'file') continue;
                    $lists[] = $file_path;
                } else {
                    $lists_children = self::_lists($file_path, $match, $filter, $depth, $type, $level + 1);
                    if (empty($lists_children)) {
                        if ($is_matched && $type !== 'file') $lists[] = $file_path;
                    } else {
                        if ($type !== 'file') $lists[] = $file_path;
                        $lists = array_merge($lists, $lists_children);
                    }
                }
            } else {
                if ($type === 'dir') continue;
                if (!empty($match) && !self::_fnmatch_array($match, $file_path)) continue; // 若未匹配, 则跳过
                $lists[] = $file_path;
            }
        }
        return $lists;
    }

    private static function _fnmatch_array($patterns, $string){
        foreach ($patterns as $pattern) if (fnmatch($pattern, $string, FNM_NOESCAPE)) return true;
        return false;
    }



    public static function rm($paths, $exclude = NULL, $level = 1){
        if(!is_array($paths))$paths = explode('|', $paths);
        $list = array();
        $dlist = array();
        foreach($paths as $k=>$path){
            if(is_file($path)){
                $list[] = $path;
            }else{
                if($level === 1 && ($flist = self::fist($path, 1, 0, 0, $exclude)) && !empty($flist))$list = array_merge($list, $flist);
                if(($dirlist = self::fist($path, 2, 0, 0, $exclude)) && !empty($dirlist)){
                    $dlist = array_merge($dlist, $dirlist);
                }else{
                    $dlist[] = $path;
                    unset($paths[$k]);
                }
            }
        }
        if($level === 1) foreach($list as $file) @unlink($file);
        foreach($dlist as $dir)@rmdir($dir);
        if($level < 16 && !empty($paths)) return self::rm($paths, $exclude, $level+1);
    }

    public static function finfo($file, $bit = 0){
        if(!$bit)$bit = is_file($file) ? 1 : 2;
        $info = pathinfo($file);
        return $bit === 1 && ($stat = stat($file)) ? array('file'=>$file, 'name'=>$info['basename'], 'type'=>$info['extension'], 'size'=>$stat['size'], 'atime'=>$stat['atime'], 'mtime'=>$stat['mtime'], 'ctime'=>$stat['ctime'], 'status'=>$bit) :
            array('file'=>$file, 'name'=>$info['basename'], 'status'=>$bit);
    }
}